package cn.z2huo.knowledge.concurrency.waitnotify;

import cn.hutool.core.thread.ThreadUtil;

import java.util.Scanner;

/**
 * <p>
 *
 * @author z2huo
 */
class WaitNotifyDemo {

    static final Object lock = new Object();

    static class WaitTarget implements Runnable {

        @Override
        public void run() {
            synchronized (lock) {
                try {
                    System.out.println("启动等待");
                    // 等待被通知，同时释放 lock 监视器的拥有权利
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("收到通知，当前线程继续执行");
        }
    }

    /**
     * 通知线程的异步目标任务
     */
    static class NotifyTarget implements Runnable {

        @Override
        public void run() {
            synchronized (lock) {
                // 从屏幕读取输入，目的是阻塞通知线程，方便使用jstack查看线程状态
                Scanner scanner = new Scanner(System.in);
                System.out.println(scanner.nextLine());
                // 获取 lock 锁，然后进行发送
                // 此时不会立即释放 lock 的 Monitor 的 Owner，需要执行完毕
                lock.notifyAll();
                System.out.println("发出通知了，但是线程还没有立马释放锁");
            }
        }
    }

    public static void main(String[] args) {
        Thread waitThread = new Thread(new WaitTarget(), "wait-thread");
        waitThread.start();
        ThreadUtil.sleep(1000);
        Thread notifyThread = new Thread(new NotifyTarget(), "notify-thread");
        notifyThread.start();
    }

/*

jps
1536
86851 Launcher
86852 WaitNotifyDemo
4133 Main
4328 FleetBootstrap
4057 Main
86968 Jps

jps 86852
2025-08-05 23:44:12
Full thread dump Java HotSpot(TM) 64-Bit Server VM (21+35-LTS-2513 mixed mode, sharing):

Threads class SMR info:
_java_thread_list=0x000060000362c0e0, length=18, elements={
0x000000012f010e00, 0x000000013e008200, 0x000000013e008a00, 0x000000012f010200,
0x000000012f011600, 0x0000000138016800, 0x0000000138017000, 0x0000000138023600,
0x000000013e820200, 0x000000013e822c00, 0x000000011f071e00, 0x000000012f018400,
0x000000013e822400, 0x000000013d00b800, 0x000000011f095e00, 0x000000011f097600,
0x000000012e810800, 0x000000012f014a00
}

"wait-thread" #29 [28931] prio=5 os_prio=31 cpu=0.13ms elapsed=30.86s tid=0x000000011f071e00 nid=28931 in Object.wait()  [0x000000016e89e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait0(java.base@21/Native Method)
        - waiting on <0x0000000380830820> (a java.lang.Object)
        at java.lang.Object.wait(java.base@21/Object.java:366)
        at java.lang.Object.wait(java.base@21/Object.java:339)
        at cn.z2huo.knowledge.concurrency.waitnotify.WaitNotifyDemo$WaitTarget.run(WaitNotifyDemo.java:24)
        - locked <0x0000000380830820> (a java.lang.Object)
        at java.lang.Thread.runWith(java.base@21/Thread.java:1596)
        at java.lang.Thread.run(java.base@21/Thread.java:1583)

"notify-thread" #36 [33795] prio=5 os_prio=31 cpu=8.55ms elapsed=29.85s tid=0x000000012e810800 nid=33795 runnable  [0x0000000a65e1e000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileInputStream.readBytes(java.base@21/Native Method)
        at java.io.FileInputStream.read(java.base@21/FileInputStream.java:287)
        at java.io.BufferedInputStream.read1(java.base@21/BufferedInputStream.java:345)
        at java.io.BufferedInputStream.implRead(java.base@21/BufferedInputStream.java:420)
        at java.io.BufferedInputStream.read(java.base@21/BufferedInputStream.java:399)
        at sun.nio.cs.StreamDecoder.readBytes(java.base@21/StreamDecoder.java:329)
        at sun.nio.cs.StreamDecoder.implRead(java.base@21/StreamDecoder.java:372)
        at sun.nio.cs.StreamDecoder.lockedRead(java.base@21/StreamDecoder.java:215)
        at sun.nio.cs.StreamDecoder.read(java.base@21/StreamDecoder.java:169)
        at java.io.Reader.read(java.base@21/Reader.java:212)
        at java.io.InputStreamReader.read(java.base@21/InputStreamReader.java:168)
        at java.util.Scanner.readInput(java.base@21/Scanner.java:890)
        at java.util.Scanner.findWithinHorizon(java.base@21/Scanner.java:1805)
        at java.util.Scanner.nextLine(java.base@21/Scanner.java:1658)
        at cn.z2huo.knowledge.concurrency.waitnotify.WaitNotifyDemo$NotifyTarget.run(WaitNotifyDemo.java:43)
        - locked <0x0000000380830820> (a java.lang.Object)
        at java.lang.Thread.runWith(java.base@21/Thread.java:1596)
        at java.lang.Thread.run(java.base@21/Thread.java:1583)


*/
}
